package cn.juct;

import com.google.common.collect.*;

import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.stream.Collectors;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;

/**
 * Hello world!
 */
public class App {


    public static void main(String[] args) {

        ConcurrentMap<String, Map<String, String>> cmp = Maps.newConcurrentMap();

        cmp.clear();

        HashMap<String, String> stringHashMap = Maps.newHashMap();
        stringHashMap.put("1", "qwer");

        //putIfAbsent方法作用
        //如果cmp存在key="1"的value，则取出value
        //如果cmp不存在key="1"的value，则添加key="1",value="value"到cmp中
        cmp.putIfAbsent("1", stringHashMap);

        System.out.println(cmp.toString());


        if (cmp.containsKey("1")) {
            System.out.println("true");
        }


        System.out.println("========================================");


        //===============================================================================================
        ConcurrentNavigableMap map = new ConcurrentSkipListMap();

        map.put("1", "one");
        map.put("2", "two");
        map.put("3", "three");

        //headMap将会指向一个仅仅包含key为“1”的ConcurrentNavigableMap，因为只有这个key是严格小于“2”的。
        // ConcurrentSkipListMap是ConcurrentNavigableMap的实现类
        // key < 2
        ConcurrentNavigableMap headMap = map.headMap("2");
        System.out.println(headMap.toString());


        //tailMap(T fromKey)返回一个包含许多键的map，其中所有键值是大于或者等于给定的fromKey的
        //tailMap将包含“2”、“3”两个键，因为这两个键是大于或者等于给定的键值“2”
        // key>=2
        ConcurrentNavigableMap tailMap = map.tailMap("2");
        System.out.println(tailMap.toString());


        //subMap()方法返回一个包含许多键的map,这些键值是介于传给该方法的（including）和（excluding）两个参数之间的
        //方法返回的subMap仅包含一个key等于“2”的键值对，因为只有这个键是大于或等“2”，并且小于“3”的
        // key>=2 & key <3
        ConcurrentNavigableMap subMap = map.subMap("2", "3");
        System.out.println(subMap);


        //==================================================================================================
        System.out.println("=========guava maps==============================");


        //不可变map
        Map<String, Integer> salary = ImmutableMap.<String, Integer>builder()
                .put("John", 1000)
                .put("Jane", 1500)
                .put("Adam", 2000)
                .put("Tom", 2000)
                .build();


        System.out.println(salary.get("John").intValue());
        System.out.println(salary.get("Tom").intValue());

        //salary初始化后，不能在更改，调用put方法会报java.lang.UnsupportedOperationException异常。
//        salary.put("qrewr",1234);


        //==========================================================================
        System.out.println("ImmutableSortedMap---有序map");

        ImmutableSortedMap<String, Integer> salary2 = new ImmutableSortedMap
                .Builder<String, Integer>(Ordering.natural())
                .put("John", 1000)
                .put("Jane", 1500)
                .put("Adam", 2000)
                .put("Tom", 3000)
                .build();

        //salary中记录按照字母进行排序
        System.out.println(salary2.firstKey());
        System.out.println(salary2.lastEntry().getValue().intValue());


        //=========================================================================
        System.out.println("===========BiMap是双向映射，但要确保值和键都唯一===========");

        BiMap<String, Integer> words = HashBiMap.create();
        words.put("First", 1);
        words.put("Second", 2);
        words.put("Third", 3);

        Integer a = words.get("Third").intValue();
        System.out.println(a);

        //BiMap.inverse() 反转map , 由 k-> v 变为 v-> k
        String k = words.inverse().get(3);
        System.out.println(k);


        //==========================================================
        //Multimap ，对每个键关联多个值
        System.out.println("Multimap ，对每个键关联多个值");
        Multimap<String, String> multimap = ArrayListMultimap.create();
        multimap.put("fruit", "apple");
        multimap.put("fruit", "banana");
        multimap.put("pet", "cat");
        multimap.put("pet", "dog");

        assertThat(multimap.get("fruit"), containsInAnyOrder("apple", "banana"));
        assertThat(multimap.get("pet"), containsInAnyOrder("cat", "dog"));


        Collection<String> collection = multimap.get("fruit");
        System.out.println(collection.toString());


        //==========================================================================

        //Lists是Guava中的一个工具类
        List<Integer> nums = Lists.newArrayList(1, null, 3, 4, null, 6);
        long cout = nums.stream().filter(num -> num != null).count();
        System.out.println(cout);

        nums.stream().filter(num -> num != null).forEach(ab -> {
            System.out.println(ab);
        });



        //------------------------------------------------------------------------

        List<String> names = new ArrayList<>();

        names.add("TaoBao");

        names.add("ZhiFuBao");

//        List<String> lowercaseNames = names.stream().map((String name) -> {
//            return name.toLowerCase();
//        }).collect(Collectors.toList());

        List<String> lowercaseNames = names.stream().map( name -> {
            return  name.toLowerCase();
        }).collect(Collectors.toList());

        System.out.println(lowercaseNames);


        //--------------------------------------------------


        Optional< String > fullName = Optional.ofNullable( null );

        //如果Optional实例有非空的值，方法 isPresent() 返回true否则返回false。
        System.out.println( "Full Name is set? " + fullName.isPresent() );


        // 方法orElseGet提供了回退机制，当Optional的值为空时接受一个方法返回默认值。
        System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) );


        // map()方法转化Optional当前的值并且返回一个新的Optional实例。
        // orElse方法和orElseGet类似，但是它不接受一个方法，而是接受一个默认值。
        System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );























        System.out.println("Hello World!");
    }
}
